package arquitetura.model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;

import to.Filme;
import to.Genero;
import to.Classificacao;
import to.Categoria;
import conexao.Conexao;
import conexao.ConexaoImpl;
import exceptions.ConexaoException;
import exceptions.ModelException;

public class ModelFilmeImpl implements ModelFilme{
private Conexao conexao;
	
	public ModelFilmeImpl(){
		conexao = ConexaoImpl.getInstancia();
    }

	@Override
	public void incluir(Filme filme) throws ConexaoException, ModelException {
		Connection conex = conexao.conectar();
        int ultimoCodigo = conexao.ultimoCodigo("Filme");
        
        String sql = "INSERT INTO Filme(codigo, nome, genero, classificacao, atores_principais, ano_lancamento, categoria) " + 
        			 "VALUES(?,?,?,?,?,?,?)";
        try {
            PreparedStatement pstm = conex.prepareStatement(sql);
            pstm.setInt(1, ultimoCodigo + 1);
            pstm.setString(2, filme.getNome());
            pstm.setInt(3, filme.getGenero().getCodigo());
            pstm.setInt(4, filme.getClassificao().getCodigo());
            pstm.setString(5, filme.getAtoresPrincipais());
            pstm.setInt(6, filme.getAnoLancamento());
            pstm.setInt(7, filme.getCategoria().getCodigo());
            pstm.executeUpdate();
            pstm.close();
        } catch (SQLException e) {
            throw new ModelException(e.getMessage());
        }finally{
        	conexao.desconectar(conex);
        }		
	}

	@Override
	public void alterar(Filme filme) throws ConexaoException, ModelException {
		Connection conex = conexao.conectar();
	        
	    String sql = "UPDATE Filme SET nome=?, genero=?, classificacao=?, atores_principais=?, ano_lancamento=?, categoria=? " +
	    			 "WHERE codigo=?";
	    try {
	        PreparedStatement pstm = conex.prepareStatement(sql);	            
	        pstm.setString(1, filme.getNome());
            pstm.setInt(2, filme.getGenero().getCodigo());
            pstm.setInt(3, filme.getClassificao().getCodigo());
            pstm.setString(4, filme.getAtoresPrincipais());
            pstm.setInt(5, filme.getAnoLancamento());
            pstm.setInt(6, filme.getCategoria().getCodigo());	        
	        pstm.setInt(7, filme.getCodigo());
	        pstm.executeUpdate();
	        pstm.close();
	    } catch (SQLException e) {
	        throw new ModelException(e.getMessage());
	    }finally{
	    	conexao.desconectar(conex);
	    }
	}

	@Override
	public void excluir(int codigo) throws ConexaoException, ModelException {
		Connection conex = conexao.conectar();		
		String sql = "DELETE FROM Filme WHERE codigo=?";
		try{
			PreparedStatement pstm = conex.prepareStatement(sql);
            pstm.setInt(1, codigo);
            pstm.executeUpdate();
            pstm.close();
        } catch (SQLException e) {
            throw new ModelException(e.getMessage());
        }finally{
        	conexao.desconectar(conex);
        }
	}

	@Override
	public Filme consultar(int codigo) throws ConexaoException, ModelException {
		Filme filme = null;
		Genero genero = null;
		Classificacao classificacao = null;
		Categoria categoria = null;
		
		Connection conex = conexao.conectar();		
		String sql = "SELECT * FROM Filme WHERE codigo = ?";
		
		try{
			PreparedStatement pstm = conex.prepareStatement(sql);
			pstm.setInt(1, codigo);
            ResultSet rs = pstm.executeQuery();
		
			if (rs.next()) {
				filme = new Filme();
				genero = new Genero();
				classificacao = new Classificacao();
				categoria = new Categoria();
				
				genero.setCodigo(rs.getInt("genero"));
				classificacao.setCodigo(rs.getInt("classificacao"));
				categoria.setCodigo(rs.getInt("categoria"));				
				
				filme.setCodigo(codigo);
				filme.setNome(rs.getString("nome"));
				filme.setGenero(genero);
				filme.setClassificacao(classificacao);
				filme.setAtoresPrincipais(rs.getString("atores_principais"));
				filme.setAnoLancamento(rs.getInt("ano_lancamento"));
				filme.setCategoria(categoria);
			}
			return filme;
	    }catch(SQLException e){
	        throw new ModelException(e.getMessage());
	    }finally{
	    	conexao.desconectar(conex);
	    }
	}

	@Override
	public Collection<String[]> listarParaGrid(String parteDoNome) throws ConexaoException, ModelException {
		Collection<String[]> lista = new ArrayList<String[]>();
		
		Connection conex = conexao.conectar();		
		String sql = "SELECT Codigo, Nome, ano_lancamento, g.descricao as genero, " +
					 "   c.descricao as classificacao, cg.descricao as categoria " +
					 "FROM Filme f" +
					 "   INNER JOIN Genero g ON f.genero = g.genero  +" +
					 "   INNER JOIN Classificacao c ON f.classificacao = c.classificacao " +
					 "   INNER JOIN Categoria cg ON f.categoria = cg.categoria ";
		
		if (! parteDoNome.trim().equals(""))
			sql = sql + "WHERE Nome like \"%" + parteDoNome + "%\" ";
		
		sql = sql + "ORDER BY Nome";
		try{
			PreparedStatement stm = conex.prepareStatement(sql);
            ResultSet rs = stm.executeQuery();
		
			while(rs.next()) {		
				lista.add(new String[] {rs.getString("codigo"), rs.getString("nome"), rs.getString("genero"), 
										rs.getString("classificacao"), rs.getString("categoria")});
			}
			return lista;
	    }catch(SQLException e){
	        throw new ModelException(e.getMessage());
	    }finally{
	    	conexao.desconectar(conex);
	    }
	}

	@Override
	public boolean filmeJahCadastrado(Filme filme) throws ConexaoException, ModelException {
		Connection conex = conexao.conectar();
		boolean jahExisteRegistro = false;
		int codigo = filme.getCodigo();
		String nome = filme.getNome();
		String sql = "";
        
		if (codigo == 0)
			sql = "SELECT Codigo FROM Filme WHERE Nome = ?";
		else
			sql = "SELECT Codigo FROM Filme WHERE Nome = ? AND Codigo <> " + codigo;
		
        try {
            PreparedStatement pstm = conex.prepareStatement(sql);
            pstm.setString(1, nome);
            ResultSet rs = pstm.executeQuery();
            
            jahExisteRegistro = rs.next();
            pstm.close();
            
            return jahExisteRegistro;
        } catch (SQLException e) {
            throw new ModelException(e.getMessage());
        }finally{
        	conexao.desconectar(conex);        	
        }
	}

	@Override
	public boolean podeExcluirFilme(int codigo) throws ConexaoException, ModelException {
		return (! existeMidiaCadastrada(codigo));
	}
	
	private boolean existeMidiaCadastrada(int codigo) throws ConexaoException, ModelException{
		Connection conex = conexao.conectar();
		boolean jahExisteRegistro = false;
		
		String sql = "SELECT Codigo FROM Midia WHERE Filme = " + codigo;		
        try {
            PreparedStatement pstm = conex.prepareStatement(sql);
            ResultSet rs = pstm.executeQuery();
            
            jahExisteRegistro = rs.next();
            pstm.close();
            
            return jahExisteRegistro;
        } catch (SQLException e) {
            throw new ModelException(e.getMessage());
        }finally{
        	conexao.desconectar(conex);        	
        } 
	}

}
